package cn.z2huo.knowledge.concurrency.threadlocal.inheritable;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * <p>
 *
 * @author z2huo
 */
@Slf4j
class Main {

    public void threadLocalTest() {
        IntegerHolder.set(20);
        log.info("parent thread {}, value is {}", Thread.currentThread().getName(), IntegerHolder.get());

        new Thread(() -> {
            IntegerHolder.increment();
            log.info("thread {}, after increment value is {}", Thread.currentThread().getName(), IntegerHolder.get());

            IntegerHolder.remove();
        }).start();
    }

    public void inheritableThreadLocalTest() {

        InheritableIntegerHolder.set(30);
        log.info("parent thread {}, value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());

        new Thread(() -> {
            InheritableIntegerHolder.increment();
            log.info("thread {}, after increment value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());

            IntegerHolder.remove();
        }).start();

    }

    public void executorServiceInheritableThreadLocalTest() {

        InheritableIntegerHolder.set(40);
        log.info("parent thread {}, value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());

        try (ExecutorService executorService = Executors.newFixedThreadPool(10)) {
            executorService.execute(() -> {
                InheritableIntegerHolder.increment();
                log.info("thread {}, after increment value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());
            });
        } finally {
            InheritableIntegerHolder.remove();
        }
    }

    public void threadPoolInheritableThreadLocalTest2() {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100)
        );
        // InheritableThreadLocal 只有在线程创建时，子线程会获取父线程中所有可继承线程局部变量的初始值
        // 因为所有的核心线程都预先创建了，所以子线程获取不到父线程中设置的值
        threadPoolExecutor.prestartAllCoreThreads();

        InheritableIntegerHolder.set(50);
        log.info("parent thread {}, value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());


        threadPoolExecutor.execute(() -> {
            InheritableIntegerHolder.increment();
            log.info("thread {}, after increment value is {}", Thread.currentThread().getName(), InheritableIntegerHolder.get());
        });

        threadPoolExecutor.close();

        InheritableIntegerHolder.remove();
    }

    public static void main(String[] args) {

        Main main = new Main();

        main.threadLocalTest();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        System.out.println();

        main.inheritableThreadLocalTest();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        System.out.println();

        main.executorServiceInheritableThreadLocalTest();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        System.out.println();

        main.threadPoolInheritableThreadLocalTest2();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        System.out.println();

    }


}
